#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DHT.h>
#include <Ticker.h>
#define DHTTYPE DHT11
#define DHTPIN 2
#define BUILTIN_LED 2
#define MSG_BUFFER_SIZE (50)

char P_NAME[] = "hanxiaoxin";
char P_PSWD[] = "314314314";
const char *ssid = P_NAME;
const char *password = P_PSWD;
const char *tcp_server = "creation-hardware.codemao.cn";

String reStr;
WiFiClient espClient;
ESP8266WebServer server(80);
Ticker time1;
unsigned long lastMsg = 0;
char msg[MSG_BUFFER_SIZE];
int value = 0;
float humidity, temp_f;           // Values read from sensor
String webString = "";            // String to display
unsigned long previousMillis = 0; // will store last temp was read
const long interval = 10000;       // interval at which to read sensor
const long uploadInterval = 15000; // interval at which to read sensor
unsigned long pre = 0; // will store last temp was read

DHT dht(DHTPIN, DHTTYPE, 11); // 11 works fine for ESP8266

void handle_root()
{
  server.send(200, "text/plain", "Hello from the weather esp8266, read from /temp or /humidity or /upload");
  delay(100);
}

void setup_wifi()
{
  delay(10);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
  }
  randomSeed(micros());
}

void getSensorData()
{
  // Wait at least 2 seconds seconds between measurements.
  // if the difference between the current time and last time you read
  // the sensor is bigger than the interval you set, read the sensor
  // Works better than delay for things happening elsewhere also
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval)
  {
    humidity = -1;
    temp_f = -1;
    
    // save the last time you read the sensor
    previousMillis = currentMillis;

    // Reading temperature for humidity takes about 250 milliseconds!
    // Sensor readings may also be up to 2 seconds 'old' (it's a very slow sensor)
    float h = dht.readHumidity();      // Read humidity (percent)
    float t = dht.readTemperature(true); // Read temperature as Fahrenheit
    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t))
    {
      humidity = -1;
      temp_f = -1;
      Serial.println("Failed to read from DHT sensor!");
      return;
    } else {
      humidity = h;
      temp_f = (t - 32) * 5 / 9;
    }
  }
}

void upload()
{
  getSensorData();
  if (!espClient.connected())
  {
    if (espClient.connect(tcp_server, 3000))
    {
      Serial.println("Client connected");
      String data = "" + String(temp_f) + "," + String(humidity);
      Serial.println(data);
      String uploadData = "{\"op\": \"upload\",\"topic\":\"Tiot_buXLoxef\",\"name\":\"dataset\",\"data\": \"" + data +
                          "\"}";
      espClient.write(uploadData.c_str());
      Serial.println("msg sent");
    }
  }
  else
  {
    if (espClient.connect(tcp_server, 3000))
    {
      Serial.println("Client connected");
      String data = "" + String(temp_f) + "," + String(humidity);
      Serial.println(data);
      String uploadData = "{\"op\": \"upload\",\"topic\":\"Tiot_buXLoxef\",\"name\":\"dataset\",\"data\": \"" + data +
                          "\"}";
      espClient.write(uploadData.c_str());
      Serial.println("msg sent");
    }
  }
}

void setup()
{
  pinMode(BUILTIN_LED, OUTPUT);
  Serial.begin(115200);

  Serial.println("\n##################################");
  Serial.println(F("ESP32 Information:"));
  Serial.printf("Internal Free Heap %d\n", ESP.getFreeHeap());
  Serial.printf("Sketch Size %d, Free Sketch Space %d\n", ESP.getSketchSize(), ESP.getFreeSketchSpace());
  Serial.printf("Cpu Freq %d, SDK Version %s\n", ESP.getCpuFreqMHz(), ESP.getSdkVersion());
  Serial.printf("Flash Size %d, Flash Speed %d\n", ESP.getFlashChipSize(), ESP.getFlashChipSpeed());
  Serial.println("##################################\n");

  Serial.println("connect wifi");
  setup_wifi();
  Serial.println(WiFi.status());
  Serial.println("RSSI: " + WiFi.RSSI());
  Serial.println("IP: " + WiFi.localIP().toString());
  Serial.println("Gateway IP: " + WiFi.gatewayIP().toString());
  Serial.println("mac: " + WiFi.macAddress());
  digitalWrite(BUILTIN_LED, HIGH);

  server.on("/", handle_root);

  server.on("/all", []()
            {
    Serial.println("on all");     
    String temp = "Temperature: " + String(temp_f) + " F";
    String hu = "Humidity: " + String(humidity) + "%";
    server.send(200, "text/plain", temp + "\n" + hu); });

  server.on("/upload", []()
            {
    Serial.println("on upload");     
    upload();
    String temp = "Temperature: " + String(temp_f) + " F";
    String hu = "Humidity: " + String(humidity) + "%";
    server.send(200, "text/plain", temp + "\n" + hu); });

  server.on("/temp", []()
            {     
    Serial.println("on temp");
    getSensorData();
    webString = "Temperature: " + String(temp_f) + " F";
    server.send(200, "text/plain", webString); });

  server.on("/humidity", []()
            {
    Serial.println("on humidity");
    getSensorData();
    webString = "Humidity: " + String(humidity) + "%";
    server.send(200, "text/plain", webString); });

  server.begin();
  Serial.println("HTTP server started");
}

void loop()
{
  unsigned long currentMillis = millis();

  unsigned long diff = currentMillis - pre;
  bool check = diff >= uploadInterval;
  // Serial.println(String(diff) + "::" + String(check));
  if (check)
  {
    pre = currentMillis; // 更新时间
    upload();
  }
  server.handleClient();
}
